package api

import (
	"context"
	"dog-blog/app/router"
	"dog-blog/base/database/sqlite"
	"dog-blog/base/global"
	"dog-blog/base/logger"
	"dog-blog/base/storage"
	"dog-blog/sdk"
	"dog-blog/sdk/pkg"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/spf13/cobra"
)

var (
	StartCmd = &cobra.Command{
		Use:          "server",
		Short:        "Start API server",
		Example:      "dog-blog server -c config/settings.yml",
		SilenceUsage: true,
		PreRun: func(cmd *cobra.Command, args []string) {
			setup()
		},
		RunE: func(cmd *cobra.Command, args []string) error {
			return run()
		},
	}
)

func setup() {
	// 加载本地数据
	storage.Load()
}

func run() error {

	basic := storage.GetBasic()
	if basic.IsEmpty() {
		log.Fatal("load config failed")
		return nil
	}

	// 初始化日志
	err := logger.GetLogger().Init()
	if err != nil {
		log.Fatal("init logger failed", err.Error())
		return nil
	}

	// 链接sqlite
	sqlite.Init()

	// 初始化路由
	if !basic.IsDebug() {
		gin.SetMode(gin.ReleaseMode)
	}
	router.InitRouter()

	// 服务配置
	srv := &http.Server{
		Addr:    fmt.Sprintf("%s:%d", basic.Host, basic.Port),
		Handler: sdk.Runtime.GetEngine(),
	}

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	// 监听服务
	go func() {
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			logger.GetLogger().E("listen:", err)
		}
	}()

	tip()

	logger.GetLogger().D(pkg.Green("Server run at:"))
	logger.GetLogger().D("-  Local:   http://localhost:%d", basic.Port)
	logger.GetLogger().D("-  Network: http://%s:%d", pkg.GetLocaHonst(), basic.Port)

	logger.GetLogger().D("Enter Control + C Shutdown Server")

	// 等待中断信号以优雅地关闭服务器
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, os.Interrupt)
	<-quit

	logger.GetLogger().D("Shutdown Server ... ")

	if err := srv.Shutdown(ctx); err != nil {
		logger.GetLogger().D("Server Shutdown:", err)
	}

	logger.GetLogger().D("Server exiting")

	return nil
}

func tip() {
	usageStr := `欢迎使用 ` + pkg.Green(`dog-blog `+global.Version) + ` 可以使用 ` + pkg.Red(`-h`) + ` 查看命令`
	fmt.Printf("%s \n\n", usageStr)
}
